//
//  main.m
//  CopyDemo
//
//  Created by FelixYin on 2020/4/12.
//  Copyright © 2020 FelixYin. All rights reserved.
//

#import <Foundation/Foundation.h>

/*
 拷贝：目的产生一个副本对象，跟源对象互不影响
 修改了源对象，不会影响副本对象
 修改了副本对象，不会影响源对象
 
 copy 不可变拷贝
 mutableCopy 可变拷贝
 
 深拷贝与浅拷贝：
 深拷贝：拷贝内容，产生新的对象
 浅拷贝：指针拷贝，没有产生新的对象
 
 
 注意：
 在MRC情况下，copy，mutableCopy的对象需要 调用release方法释放
 
 */

// MARK: NSString

void test(){
    NSString *str = @"1243";
    NSString *str2 = [str copy];
    str2 = @"456";
    
    NSLog(@"str == %@ str2 == %@",str,str2);
    [str2 release];
}

void test1(){
    NSString *str = [NSString stringWithFormat:@"%@",@"StringStringStringStringStringString"];
    NSString *str1 = [str copy]; //返回的是NSString
//    NSMutableString *str1 = [str copy]; //返回的是NSString
//    [str1 appendString:@"99999"];
    NSMutableString *str2 = [str mutableCopy]; //返回的是MutableString
    [str2 appendString:@"8888"]; //如果为可拼接字符串，可以证明mutableCopy 之后的对象类型为MutableCopy
    
    
    NSMutableString *str3 = [[NSMutableString alloc] initWithString:@"MutableString"];
    NSString *str4 = [str3 copy]; //copy之后为不可变String
//    NSMutableString *str4 = [str3 copy];
//    [str4 appendString:@"222"];
    NSMutableString *str5 = [str3 mutableCopy]; //mutableString 为可变String
    [str5 appendString:@"111"];
    
    
    NSLog(@"str == %@ str1 == %@ str2 == %@",str,str1,str2);
    NSLog(@"str class == %@ str1 class == %@ str2 class == %@",[str class],[str1 class],[str2 class]);
    NSLog(@"str3 == %@ str4 == %@ str5 == %@",str3,str4,str5);
    
    [str release];
    [str1 release];
    [str2 release];
    [str3 release];
    [str4 release];
    [str5 release];
}

void test2(){
    
    //注意当字符串比较短的时候，苹果使用TagPointer计数 NSString对象引用计数为-1，当想看到引用计数效果的话需要使用足够长的字符创
    NSString *str = [[NSString alloc] initWithFormat:@"StringStringStringStringStringStringStringString"];
    
    NSLog(@"str ReatinCount = %ld",str.retainCount); //引用计数为1
    
    NSString *str1 = [str copy]; //引用计数为2（浅拷贝,虽然不产生新的对象，但引用计数会加1,所以当不使用的时候 需要release）
    
    NSLog(@"str ReatinCount = %ld",str.retainCount);
    
    NSString *str2 = [str mutableCopy];
    
    /*
     结果分析：str == 0x100001178 str1 == 0x100001178 str2 == 0x1007251d0
     str的地址跟str1是一样的，str2是一个新的地址。因为str,str1都是不可变对象，内容都没有办法修改
     为了节省内存，str跟str1 指向同一个内存地址。而mutableCopy是一个可变的，所以就需要重新分配内存
     地址也就是不一样了
    
     
     */
    NSLog(@"str == %p str1 == %p str2 == %p",str,str1,str2);
    
    [str release];
    [str1 release];
    [str2 release];
}


void test3(){
    NSMutableString *str = [[NSMutableString alloc] initWithString:@"MutableString"];
    NSString *str1 = [str copy]; //深拷贝
    NSString *str2 = [str mutableCopy]; //深拷贝
    //str == 0x10054eaa0 str1 == 0x10054f020 str2 == 0x10054f0c0 
    NSLog(@"str == %p str1 == %p str2 == %p",str,str1,str2);
    
    [str release];
    [str1 release];
    [str2 release];
}

// MARK: NSArray

void test4(){
    NSArray *array1 = [[NSArray alloc] initWithObjects:@"a",@"b",@"c", nil];
    NSArray *array2 = [array1 copy]; //浅拷贝，指针拷贝，引用计数加1
    NSLog(@"array1 RetainCount %ld  array2 RetainCount %ld",array1.retainCount,array2.retainCount);
    NSMutableArray *array3 = [array1 mutableCopy];//深拷贝，产生新对象
    
    NSLog(@"array1 RetainCount %ld  array2 RetainCount %ld array3 RetainCount %ld",array1.retainCount,array2.retainCount,array3.retainCount);
    
    //array1 0x1020a47f0  array2 0x1020a47f0  array3 0x102102780
    NSLog(@"%p  %p  %p",array1,array2,array3);
    
    //不使用时 需要释放
    [array1 release];
    [array2 release];
    [array3 release];
}


// MARK: NSDictionary

void test5(){
    //写法是：value=key
    NSDictionary *dict1 = [[NSDictionary alloc] initWithObjectsAndKeys:@"jack",@"name",@"Felix",@"name", nil];
    NSDictionary *dict2 = [dict1 copy];
//    dict1 RetainCount 2  dict2 RetainCount 2
    NSLog(@"dict1 RetainCount %ld  dict2 RetainCount %ld",dict1.retainCount,dict2.retainCount);
    NSDictionary *dict3 = [dict1 mutableCopy];
    
//    dict1 RetainCount 2  dict2 RetainCount 2 dict3 RetainCount 1
    NSLog(@"dict1 RetainCount %ld  dict2 RetainCount %ld dict3 RetainCount %ld",dict1.retainCount,dict2.retainCount,dict3.retainCount);
    
    //dict1 0x10063e4c0 dict2 0x10063e4c0 dict3 0x100500040
    NSLog(@"%p  %p  %p",dict1,dict2,dict3);
    [dict1 release];
    [dict2 release];
    [dict3 release];
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        /*
         NSString
         */
//        test();
//        test1();
//        test2();
//        test3();
        
        /*
         NSArray
         */
//        test4();
        
        /*
         NSDictionary
         */
        test5();
    }
    return 0;
}
